"""

.. module:: htmltask
.. moduleauthor:: @author: 

The purpose of this module is ... 
   
.. seealso:: modules :mod:`<module>`

*Constants*:
.. data:: constant_1
        
    constant_1 is used for ......
        
.. data:: constant_2
        
    constant_2 is used for ......
"""

# Imports
#
import logging
import json
import time
from datetime import datetime
import types

from runtime.task import Task
from runtime.spaces import *
from runtime.boot import LoggingLevels
from datastore import *
from services import *
from services.httpserver import *       # FIXME: not sure why I need this

# Constants
#

# Classes
#


class HTMLTask(Task):
    """This class has been replaced by TransformTask.
    
    *** HTMLTask will be replaced by TransformTask. ***
    *** HTMLTask will be replaced by TransformTask. ***
    *** HTMLTask will be replaced by TransformTask. ***
    *** HTMLTask will be replaced by TransformTask. ***
    *** HTMLTask will be replaced by TransformTask. ***
    *** HTMLTask will be replaced by TransformTask. ***

    *Usage examples*::

        html_uri = self.spaces_context.uri('html:').template.basic
        data = Resource()
        data.hello = 'World!'
        generated_html_uri = self.spaces_context.put(html_uri, data)    # HTML generated when this returns
        gen_res = self.spaces_context.remove(generated_html_uri)        # get then delete the generated html
        print(gen_res)

    *Common Arguments for Class methods*:
        <arguments>
    
    *Audience*:
        <audience>
    
    *Constants*:
        .. data:: constant_1
        
            constant_1 is used for ......
        
        .. data:: constant_2
        
            constant_2 is used for ......
    """
    
    # Class constants
    #
    
    def __init__(self, ds, spaces, task_uri, task_def_rs):
        # <purpose>
        #
        # Parameters:
        #     ds : datastore.database.DataStore
        #     spaces : runtime.spaces.Spaces - Reference to spaces
        #     task_uri : String - the uri for this task. The root uri will most
        #                likely be the 'binding' uri for this task.
        #     task_def_rs : datastore.resource.Resource - Task definition resource.
        #
        
        Task.__init__(self, ds, spaces, task_uri, task_def_rs)
        
        self.logger = logging.getLogger('yarra.services.htmltask.HTMLTask')
        self.logger.log(logging.DEBUG, "ds (%s), spaces (%s), task_uri (%s), task_def_rs (%s)" % (ds, spaces, task_uri, task_def_rs.pretty_print()))
        
    def cb_start(self, method, uri, new_uri, result, context, **kwargs):
        """This function is called when the task starts. uri is the task URI.
        Register all templates as html:template/xxx for the template Resource
        and html:template/xxx/ for the generation function.
        
        :param method: <class> or <type>
        :param uri: <class> or <type>
        :param new_uri: <class> or <type>
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        """
        
        self.template = self.spaces_context.uri('html:').template
        self.template_list = {'basic': self.template.basic}
        #
        for template in self.template_list:
            # TODO: fetch the template Resource from the datastore.
            # TODO: put it to html:template/xx to allow access during generation.
            watch_put_key = self.spaces_context.process(self.template_list[template].collection(), put='cb_generate')
            self.logger.log(logging.DEBUG, "Add process(put) for: %s" % self.template_list[template])
        
        #assume that we put the real resource after generation.
        #watch_remove_key = self.spaces_context.process_all(self.templates, remove='cb_fetch')
        #
    
    def cb_generate(self, method, uri, res, result, context, **kwargs):
        """This function generates HTML as a result of a 'put' to  'put'.
        The resource containing the input data is passed to this callback.
        Doesn't return until generation is complete.
        Returns the URI of the generated HTML.
        
        :param method: <class> or <type>
        :param uri: <class> or <type>
        :param res: <class> or <type>
        :param result: <class> or <type>
        :param context: <class> or <type>
        :param kwargs: <class> or <type>
        :rtype: 
        """
        
        # we only want to process puts by the user of this API, not ours...
        if uri in self.template_list.values():
            html_uri = context.uri('html:')
            gen_uri = html_uri.output.add(self.spaces_context.uuid())
            
            self.logger.log(logging.DEBUG, "Creating generated HTML (%s) using: %s" % (gen_uri, str(res)))
            
            html_res = Resource()
            html = ''
            if uri == context.uri('html:template/basic/'):
                # The basic template creates hard coded HTML for any Resource.
                html += '<html>\n<body>\n'
                html += '<h1>Metadata</h1>\n<table border=1>\n'
                for meta in res.get_metadata_keys():
                    html += '<tr><td>%s</td><td>' % meta
                    for value in res.get_metadata(meta):
                        html += '%s<br>' % value
                    html += '</td></tr>\n'
                html += '</table>\n'
                html += '<h1>Data</h1>\n'
                html += self._gen_html(res.get_vars())
                #html += '<hr><small>generated HTML URI: %s - %s</small>\n' % (gen_uri.full(), datetime.now())
                html += '<hr><small>generated HTML URI: %s - %%s</small>\n' % gen_uri.full()
                html += '</body></html>\n'
                #
                def fix_footer(html):
                    from datetime import datetime
                    return html % datetime.now()
                html_res.finalise = [fix_footer]
            else:
                html = "<html>%s</html>" % res.hello
            html_res.content = html
            context.put(gen_uri, html_res)
            return (True, gen_uri)
        else:
            self.logger.log(logging.ERROR, "HTML Template not found for: %s" % uri)
            return (True, None)

    def _gen_html(self, var):
        """This function generates HTML for the argument 'var' dictionary.
        
        :param var: dict or resource.ResourceDict
        :rtype: string - HTML
        """
        
        html = ''
        # FIXME: we shouldn't need resource.ResourceDict, just ResourceDict
        if type(var) in [types.DictType, type(resource.ResourceDict())]:
            html += '<table border=1>\n'
            keys = var.keys()
            keys.sort()
            for key in keys:
                html += '<tr>'
                html += '<td>%s</td>' % key
                html += '<td>%s</td>' % self._gen_html(var[key])
                html += '</tr>\n'
            html += '</table>\n'
        elif type(var) in [types.ListType, types.TupleType]:
            html += '<table border=1>\n'
            for value in var:
                html += '<tr>'
                html += '<td>%s</td>' % self._gen_html(value)
                html += '</tr>\n'
            html += '</table>\n'
        elif var is not None:
            html += var
        return html
    
#    def cb_fetch (self, method, uri, return_value, result, context):
#        '''
#        Retrieve the resource with the generated HTML and then delete it using 'remove'.
#        Returns a resource containing the generated HTML.
#        '''
#        res = self.spaces_context.get(uri)
#        return (True, res)


#if __name__ == "__main__":
#    pass
    
